﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Rotempco.BaseClass.Objects.ResultObjects;
using Rotempco.Core.ORM.Managers;
using Rotempco.BaseClass.Objects.EntityObjects;
using Rotempco.BaseClass.DAL;
using Rotempco.BaseClass.Objects.Enums;
using Rotempco.BaseClass.Logic;
using Rotempco.Core.Logic;
using Rotempco.BaseClass.Objects.ReturnObjects;

namespace Rotempco.BaseClass.Managers
{
    public class LoginUserManager : LoginUserData
    {
        public override void WriteToDB(LoginUser loginUser)
        {
            if (loginUser.LoginUserId == 0)
                loginUser.CreatedDate = DateTime.Now;

            DatabaseManager.Instance.Transact(() =>
            {
                DataFactory.LoginUser.WriteToDB(loginUser);
            });
        }

        public override void Delete(long id, bool forceDelete = false)
        {
            DatabaseManager.Instance.Transact(() =>
            {
                DataFactory.LoginUser.Delete(id, forceDelete);
            });
        }

        public CreateNewLoginUserResultEnum ValidateNewLoginUser(LoginUser loginUser)
        {
            string email = loginUser.Email.Trim().ToLower();

            if (!EmailLogic.IsValidEmail(email))
                return CreateNewLoginUserResultEnum.InvalidEmail;

            //if (loginUser.LoginUserId == 0)
            //{
            // Email must be unique:
            LoginUser existingUser = Factory.LoginUser.GetSingle(email: email);
            if (existingUser != null && existingUser.LoginUserId != loginUser.LoginUserId)
                return CreateNewLoginUserResultEnum.UserAllreadyExists;
            //}

            return CreateNewLoginUserResultEnum.Success;
        }

        public CreateNewLoginUserResult CreateNewLoginUser(string name, string email)
        {
            CreateNewLoginUserResultEnum validationResult = ValidateNewLoginUser(new LoginUser() { Name = name, Email = email });

            if (validationResult != CreateNewLoginUserResultEnum.Success)
                return new CreateNewLoginUserResult(validationResult);

            // Fetch asymemtric private encryption key:
            string privateAsymmetricEncryptionKey = CoreSettingsLogic.GetPrivateDecryptionKey();

            email = email.Trim().ToLower();

            string randomPassword = PasswordLogic.GetRandomPassword();

            LoginUser loginUser = new LoginUser()
            {
                ChangePasswordOnNextLogin = true,
                PasswordHash = HashLogic.GetHash(randomPassword),
                Email = email,
                Name = name,
            };

            PasswordHistory passwordHistory = new PasswordHistory()
            {
                CreatedDate = DateTime.Now,
                LoginUserId = loginUser.LoginUserId,
                PasswordHash = loginUser.PasswordHash
            };

            string subject = "Rotempco has created an account for you.";
            string message = "Your temporary password is " + randomPassword;

            DatabaseManager.Instance.Transact(() =>
            {
                Factory.EmailQueue.AddToEmailQueue(loginUser.Email, subject, message);
                WriteToDB(loginUser);
            });

            return new CreateNewLoginUserResult(CreateNewLoginUserResultEnum.Success, loginUser);
        }

        public LoginResult Login(string email, string password)
        {
            string passwordHash = HashLogic.GetHash(password.Trim());
            LoginResult loginResult = LoginLogic.Login(email, passwordHash);

            if (loginResult.LoginResultEnum == LoginResultEnum.Success || loginResult.LoginResultEnum == LoginResultEnum.ChangePassword)
            {
                //LoginLogic.SetStores(loginResult.LoginUser);
            }

            return loginResult;
        }

        public ChangePasswordResultEnum ChangePassword(LoginUser loginUser, string newPassword)
        {
            if (!PasswordLogic.IsValidPassword(newPassword))
                return ChangePasswordResultEnum.InvalidPassword;

            //if (string.IsNullOrWhiteSpace(CoreSettingsLogic.GetPrivateDecryptionKey()))
            //    return ChangePasswordResultEnum.EncryptionKeyError;

            loginUser.PasswordHash = HashLogic.GetHash(newPassword);
            loginUser.ChangePasswordOnNextLogin = false;


            PasswordHistory passwordHistory = new PasswordHistory()
            {
                CreatedDate = DateTime.Now,
                LoginUserId = loginUser.LoginUserId,
                PasswordHash = loginUser.PasswordHash
            };

            DatabaseManager.Instance.Transact(() =>
            {
                Factory.PasswordHistory.WriteToDB(passwordHistory);
                WriteToDB(loginUser);
            });

            //LoginLogic.SetStores(loginUser);
            return ChangePasswordResultEnum.Success;
        }


        public ResetPasswordResultEnum ResetPassword(string email)
        {
            email = email.Trim().ToLower();

            LoginUser loginUser = Factory.LoginUser.GetSingle(email: email);

            if (loginUser == null)
                return ResetPasswordResultEnum.LoginUserNotFound;

            string randomPassword = PasswordLogic.GetRandomPassword();

            loginUser.ChangePasswordOnNextLogin = true;
            loginUser.PasswordHash = HashLogic.GetHash(randomPassword);

            PasswordHistory passwordHistory = new PasswordHistory()
            {
                CreatedDate = DateTime.Now,
                LoginUserId = loginUser.LoginUserId,
                PasswordHash = loginUser.PasswordHash
            };

            string subject = "Rotempco reset password request";
            string message = "You have requested a password request. Your temporary password is " + randomPassword;

            DatabaseManager.Instance.Transact(() =>
            {
                Factory.EmailQueue.AddToEmailQueue(loginUser.Email, subject, message);
                Factory.PasswordHistory.WriteToDB(passwordHistory);
                WriteToDB(loginUser);
            });

            return ResetPasswordResultEnum.Success;
        }

        public void Logoff()
        {
            //LoginStore.Instance.Clear();
            CoreSettingsLogic.ClearPrivateDecryptionKey();
        }

    }
}
